package com.coolw.spring.statemachine.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.coolw.common.api.BaseResult;
import com.coolw.spring.statemachine.dto.OrderDTO;
import com.coolw.spring.statemachine.entity.OrderEntity;
import com.coolw.spring.statemachine.enums.MachineIdEnum;
import com.coolw.spring.statemachine.enums.OrderEvent;
import com.coolw.spring.statemachine.enums.OrderStatusEnum;
import com.coolw.spring.statemachine.mapper.OrderMapper;
import com.coolw.spring.statemachine.service.OrderService;
import com.coolw.spring.statemachine.support.StateMachineHolder;
import com.coolw.spring.statemachine.support.order.OrderContext;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.bean.BeanUtil;
import org.dromara.hutool.core.data.id.IdUtil;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.text.StrUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 订单服务实现类
 *
 * @author coolw
 * @date 2024/4/8 16:40
 */
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderEntity> implements OrderService {

    private final MachineIdEnum machineId = MachineIdEnum.ORDER;

    @Resource
    private StateMachineHolder<OrderStatusEnum, OrderEvent, OrderContext, String> stateMachineHolder;

    @Override
    public BaseResult<String> create(OrderDTO orderDTO) {
        String orderId = IdUtil.getSnowflakeNextIdStr();

        // 保存订单
        OrderEntity order = BeanUtil.copyProperties(orderDTO, OrderEntity.class);
        order.setOrderId(orderId);
        order.setOrderStatus(OrderStatusEnum.WAIT_PAYMENT.getCode());
        save(order);

        return BaseResult.success(orderId);
    }

    @Override
    public BaseResult<Boolean> pay(String orderId) {
        OrderEntity order = checkOrderAndReturn(orderId);

        OrderStatusEnum orderStatusEnum = OrderStatusEnum.getEnum(order.getOrderStatus());
        OrderContext context = new OrderContext(order.getOrderId(), orderStatusEnum);

        boolean send = stateMachineHolder.sendEvent(OrderEvent.PAYED, context, context.getOrderId(), machineId);
        if (!send) {
            return BaseResult.fail("支付失败,订单状态异常");
        }
        return BaseResult.success(true);
    }

    @Override
    public BaseResult<Boolean> deliver(String orderId) {
        OrderEntity order = checkOrderAndReturn(orderId);

        OrderStatusEnum orderStatusEnum = OrderStatusEnum.getEnum(order.getOrderStatus());
        OrderContext context = new OrderContext(order.getOrderId(), orderStatusEnum);

        boolean send = stateMachineHolder.sendEvent(OrderEvent.DELIVERY, context, context.getOrderId(), machineId);
        if (!send) {
            return BaseResult.fail("发货失败,订单状态异常");
        }
        return BaseResult.success(true);
    }

    @Override
    public BaseResult<Boolean> receive(String orderId) {
        OrderEntity order = checkOrderAndReturn(orderId);

        OrderStatusEnum orderStatusEnum = OrderStatusEnum.getEnum(order.getOrderStatus());
        OrderContext context = new OrderContext(order.getOrderId(), orderStatusEnum);

        boolean send = stateMachineHolder.sendEvent(OrderEvent.RECEIVED, context, context.getOrderId(), machineId);
        if (!send) {
            return BaseResult.fail("收获失败,订单状态异常");
        }
        return BaseResult.success(true);
    }

    private OrderEntity checkOrderAndReturn(String orderId) {
        OrderEntity order = getOneByOrderId(orderId);
        Assert.notNull(order, StrUtil.format("[{}]订单不存在", orderId));
        return order;
    }

    @Override
    public boolean updateOrderStatus(String orderId, OrderStatusEnum orderStatusEnum) {
        Assert.notBlank(orderId, "订单ID不能为空");
        Assert.notNull(orderStatusEnum, "订单状态不能为空");

        LambdaUpdateWrapper<OrderEntity> updateWrapper = Wrappers.<OrderEntity>lambdaUpdate()
                .set(OrderEntity::getOrderStatus, orderStatusEnum.getCode())
                .eq(OrderEntity::getOrderId, orderId);
        return update(updateWrapper);
    }

    @Override
    public OrderEntity getOneByOrderId(String orderId) {
        Assert.notBlank(orderId, "订单ID不能为空");

        LambdaQueryWrapper<OrderEntity> queryWrapper = Wrappers.<OrderEntity>lambdaQuery()
                .eq(OrderEntity::getOrderId, orderId);
        return getOne(queryWrapper);
    }

    /**
     * 发送订单状态转换事件
     */
    /*private synchronized boolean sendEvent(OrderEvent orderEvent, OrderDTO orderDTO) {
        boolean result;
        try {
            orderStateMachine.start();

            // 尝试恢复状态机状态
            stateMachineMemPersister.restore(orderStateMachine, orderDTO.getOrderId());

            Message<OrderEvent> message = MessageBuilder.withPayload(orderEvent)
                    .setHeader("orderContext", orderDTO)
                    .build();

            // 触发事件
            result = orderStateMachine.sendEvent(message);

            // 持久化状态机信息
            stateMachineMemPersister.persist(orderStateMachine, orderDTO.getOrderId());
        } catch (Exception e) {
            log.error("订单操作失败,orderDTO:{},orderEvent:{}", orderDTO, orderEvent, e);
            throw BusinessExceptionUtils.create("订单操作失败");
        } finally {
            orderStateMachine.stop();
        }
        return result;
    }*/
}
